﻿param($computerNamePrefix,$startingComputerNumber,$clusterNodeCount,$mediaPath,$basePath,$targetBasePath,$administratorPassword,$domainName,$fullDomainName,$virtualSwitchName,$dcName,$dcCredential,$dcPassword,$baseIpRange,$dnsIpAddress,$defaultGateway,$clusterName,$clusterIp,$clusterType,$diskCountPerNode,$diskSizeInGB)

Import-Module ..\BuildDeployment\libUtilities.psm1
Import-Module -Force .\libVM.psm1
Import-Module FailoverClusters
Import-Module .\NanoServerImageGenerator.psm1




New-SmbMapping -LocalPath X: -RemotePath \\$dcName\Blobs -UserName $dcCredential.UserName -Password $dcPassword -ErrorAction SilentlyContinue


$dcSession=Assert-PSSession -computerAddress $dcName`.$fullDomainName -Credential $dcCredential -useCredSSP

Write-Host "Destroying existing cluster $clusterName"
$command = {param($clusterName) Get-Cluster -Name $clusterName -ErrorAction SilentlyContinue | Remove-Cluster -CleanupAD -Force -ErrorAction SilentlyContinue}
Invoke-Command -Session $dcSession -ScriptBlock $command -ArgumentList $clusterName,$clusterIp,$clusterNodes

Write-Host "Removing cluster computer object from the AD"
$command={ param($clusterName) 
            try
            {                     
                $clusterComputerObject=Get-ADComputer $clusterName -ErrorAction SilentlyContinue
                if($clusterComputerObject -ne $null -and $clusterComputerObject.Name -ne $null)
                {
                    $clusterComputerObject | Remove-ADComputer -Confirm:$false -ErrorAction SilentlyContinue
                }
            }
            catch
            {
                Write-Host $_.MessageText
            }

            try
            {                     
                $sofsComputerObject=Get-ADComputer DV-FSS -ErrorAction SilentlyContinue
                if($sofsComputerObject -ne $null -and $sofsComputerObject.Name -ne $null)
                {
                    $sofsComputerObject | Remove-ADComputer -Confirm:$false -ErrorAction SilentlyContinue
                }
            }
            catch
            {
                Write-Host $_.MessageText
            }
             
         }
Invoke-Command -Session $dcSession -ScriptBlock $command -ArgumentList $clusterName


$clusterNodes=@()

for($i=0;$i -lt $clusterNodeCount;$i++)
{
    $computerName=$computerNamePrefix+($startingComputerNumber+$i)
    $clusterNodes+=$computerName
    $targetPath=$targetBasePath+$computerName

    Write-Host "Stopping $computerName"
    Stop-VM -Name $computerName -TurnOff -Force -ErrorAction SilentlyContinue
    
    Write-Host "Deleting $computerName"
    Remove-VM -Name $computerName -Force -ErrorAction SilentlyContinue

    Write-Host "Remove Hyper-V files for $computerName"
    Remove-Item -Recurse $targetPath -Force -ErrorAction SilentlyContinue
    
    Write-Host "Removing cluster node computer account from the AD"
    $command={ param($computerName,$domainName)
                try
                {
                    $existingComputerAccount=Get-ADComputer $computerName
                    if($existingComputerAccount -ne $null)
                    {
                        Remove-ADComputer $computerName  -Confirm:$false -ErrorAction SilentlyContinue; 
                    }
                }
                catch
                {
                    Write-Host "$computerName doesn't exist in the AD"
                }
                }
    Invoke-Command -Session $dcSession -ScriptBlock $command -ArgumentList $computerName,$domainName
    
    

    $dcJoinBlobPath="Y:\$computerName.blob"
 

    $command={ param($computerName,$domainName)
                Remove-Item -Path "C:\blobs\$computerName.blob" -Force -Confirm:$false
                djoin /Provision /Domain $domainName /Machine $computerName /SaveFile "C:\blobs\$computerName.blob"}

    
    
    Write-Host "Generating AD join blob"
    Invoke-Command -Session $dcSession -ScriptBlock $command -ArgumentList $computerName,$domainName   
    
    
    
    
    Write-Host "Generating Nano Server image for $computerName"
    New-NanoServerImage -MediaPath $mediaPath -BasePath $basePath -TargetPath ("$targetPath\$computerName`_OS.vhdx") -DeploymentType Guest -Storage -Clustering -AdministratorPassword $administratorPassword -DomainBlobPath $dcJoinBlobPath -EnableRemoteManagementPort -Edition Datacenter
 
    Write-Host "Creating VM for $computerName"
    New-VM -Name $computerName -MemoryStartupBytes 256MB -SwitchName $virtualSwitchName -VHDPath ("$targetPath\$computerName`_OS.vhdx") -Path $targetPath -Generation 2
    Set-VM -Name $computerName -DynamicMemory -MemoryMinimumBytes 128MB
     
 
    Write-Host "Starting $computerName"
    Start-VM $computerName

    for($j=0;$j -lt $diskCountPerNode;$j++)
    {
        New-VHD -Path $targetPath\$computerName`_DAT_00$j.vhdx -SizeBytes ($diskSizeInGB*1GB) -Dynamic
        Add-VMHardDiskDrive -VMName $computerName -Path $targetPath\$computerName`_DAT_00$j.vhdx -ControllerType SCSI
    }

    #Allow VM to boot up
    Start-Sleep -Seconds 30
    
    $currentIpAddress=(Get-VMNetworkAdapter -VMName $computerName).IpAddresses[0]
    Set-Item WSMan:\localhost\Client\TrustedHosts -Value $currentIpAddress -Concatenate -Force
    $ipAddress=$baseIpRange + (50+$i)

    while($currentIpAddress -ne $ipAddress)
    {
        Write-Host "IP not detected, attempting to set..."
        $networkAdapter=(Get-VMNetworkAdapter -VMName $computerName)[0] 
        $networkAdapter | Set-VMNetworkConfiguration -IPAddress $ipAddress -Subnet "255.255.255.0" -DefaultGateway $defaultGateway
        $currentIpAddress=(Get-VMNetworkAdapter -VMName $computerName).IpAddresses[0]
        Start-Sleep -Seconds 5
    }

    Set-Item WSMan:\localhost\Client\TrustedHosts -Value $currentIpAddress -Concatenate -Force
        
    Set-Item WSMan:\localhost\Client\TrustedHosts -Value $computerName`.$fullDomainName -Concatenate -Force

    $localCredential = New-Object System.Management.Automation.PSCredential ("$computerName\administrator", $administratorPassword)
    

    Write-Host "Setting DNS and firewall rules for $computerName"
    $vmSession=Assert-PSSession -computerAddress $currentIpAddress -credential $localCredential
    $command={ param($dnsIpAddress,$defaultGateway)  
                netsh interface ipv4 add dnsserver "Ethernet" address=$dnsIpAddress  index=1;
                Register-DnsClient
                netsh advfirewall firewall add rule name="Local Any" dir=inaction=allow profile=any remoteip=any;
                }
    Invoke-Command -Session $vmSession -ScriptBlock $command -ArgumentList $dnsIpAddress,$defaultGateway
    
    Remove-PSSession -Session $vmSession
}

Start-Sleep -Seconds 30

$dcSession=Assert-PSSession -computerAddress $dcName`.$fullDomainName -credential $dcCredential -useCredSSP
Write-Host "Creating cluster $clusterName"
$command = {param($clusterName,$clusterIp,$clusterNodes) Import-Module FailoverClusters;

            New-Cluster -Name $clusterName -Node $clusterNodes[0] -StaticAddress $clusterIp -NoStorage;
            $cluster=Get-Cluster -Name $clusterName
            
            for($i=1;$i -lt $clusterNodes.Count;$i++)
            {
                Add-ClusterNode -Name $clusterNodes[$i] -NoStorage -Cluster $cluster
            }
            }

Invoke-Command -Session $dcSession -ScriptBlock $command -ArgumentList $clusterName,$clusterIp,$clusterNodes
<#
if($clusterType -eq "StorageSpacesDirect")
{
    Write-Host "Enabling Storage Spaces Direct on $clusterName"
    $command = {param($clusterName) Import-Module FailoverClusters; 
               Enable-ClusterStorageSpacesDirect -Cluster (Get-Cluster -Name $clusterName) -S2DCacheMode Disabled -SkipEligibilityChecks;
               }
    Invoke-Command -Session $dcSession -ScriptBlock $command -ArgumentList $clusterName

    Write-Host "Adding File-Services features on $clusterName"
    $command = {param($clusterNodes) 
                foreach($clusterNode in $clusterNodes)
                {
                    try
                    {
                        Add-WindowsFeature -ComputerName $clusterNode -Name File-Services -IncludeManagementTools -ErrorAction SilentlyContinue
                    }
                    catch
                    {
                        Write-Host $_.MessageText
                    }
                }
               }
    Invoke-Command -Session $dcSession -ScriptBlock $command -ArgumentList $clusterNodes
    
    $userName=$clusterNodes[0] + "\administrator" 
    $localCredential = New-Object System.Management.Automation.PSCredential ($userName, $administratorPassword)
    $computerAddress=$clusterNodes[0] + ".$fullDomainName"
    $vmSession=Assert-PSSession -computerAddress $computerAddress -credential $localCredential

    Write-Host "Creating Storage Spaces Direct pool on $clusterName"
    $command = {
                    param($clusterName,$fullDomainName)
                    New-StoragePool -StorageSubSystemName $clusterName`.$fullDomainName -FriendlyName POOL-001 -WriteCacheSizeDefault 0 -FaultDomainAwarenessDefault StorageScaleUnit -ProvisioningTypeDefault Fixed -ResiliencySettingNameDefault Mirror -PhysicalDisk (Get-StorageSubSystem -Name $clusterName`.$fullDomainName | Get-PhysicalDisk)
                }
    Invoke-Command -Session $vmSession -ScriptBlock $command -ArgumentList $clusterName,$fullDomainName

    Write-Host "Creating Storage Spaces virtual disk on $clusterName"
    $command = {
                    param($clusterName,$fullDomainName)
                    #Create virtual disks
                    New-Volume -StoragePoolFriendlyName POOL-001 -FriendlyName POOL-001-VD-001 -PhysicalDiskRedundancy 2 -FileSystem CSVFS_REFS –Size 10GB
                    Rename-Item C:\ClusterStorage\Volume1 -NewName C:\ClusterStorage\POOL-001-VD-001
                    #Disable ReFS Integrity Streams by Default on Volume
                    #Can be Re-enabled on Individual Files or Folders as Desired
                    Set-FileIntegrity C:\ClusterStorage\POOL-001-VD-001 –Enable $false
                }
    Invoke-Command -Session $vmSession -ScriptBlock $command -ArgumentList $clusterName,$fullDomainName
    
    Write-Host "Adding DNS entries for DV-FSS"
    $command = {param($clusterNodes,$baseIpRange,$fullDomainName) 
                Import-Module DnsServer
                
                for($i=0;$i -lt $clusterNodes.Count;$i++)
                {
                    $ipAddress=$baseIpRange + (50+$i)
                    Remove-DnsServerResourceRecord -ZoneName adrenaline.local -Name DV-FSS -RRType A -RecordData $ipAddress -ErrorAction SilentlyContinue -Confirm:$true
                    Add-DnsServerResourceRecord -ZoneName $fullDomainName -IPv4Address $ipAddress -Name DV-FSS -A
                       
                }
               }
    Invoke-Command -Session $dcSession -ScriptBlock $command -ArgumentList $clusterNodes,$baseIpRange,$fullDomainName
    
    
    Write-Host "Creating SOFS on $clusterName"
    $command = {
                    param($clusterName,$fullDomainName)
                    New-StorageFileServer  -StorageSubSystemName $clusterName`.$fullDomainName -FriendlyName DV-FSS -HostName DV-FSS -Protocols SMB
                }
    Invoke-Command -Session $vmSession -ScriptBlock $command -ArgumentList $clusterName,$fullDomainName
    
    Write-Host "Creating Share on $clusterName"
    $command = {
                    param($clusterName,$fullDomainName)
                    $shareName = "CSV1"
                    $sharePath = "C:\ClusterStorage\POOL-001-VD-001\$shareName"

                    md $sharePath
                    New-SmbShare -Name $shareName -Path $sharePath

                }
    Invoke-Command -Session $vmSession -ScriptBlock $command -ArgumentList $clusterName,$fullDomainName
        
}
#>
Remove-PSSession -Session $dcSession
Remove-PSSession -Session $vmSession